package main

import (
	"fmt"
	"go-base-learning/src/09_func_and_package/package/utils"
)

type mySum func(float64, float64) float64

var globalN1 int = 0

var func1 = func(n1 int, n2 int) int {
	return n1 * n2
}

func init() {
	globalN1 = 1
	fmt.Println("init, globalN1=", globalN1)
}

func main() {
	fmt.Println("main, globalN1=", globalN1)
	//calculateTest()
	//var n int = 11
	//var i int = 1
	//recursiveTest(n, i)
	//arg1, arg2 := justReturnArgs(1, "asda")
	//fmt.Println("justReturnArgs: ", arg1, arg2)

	/*
		1、基本数据类型和数组默认是值传递，函数内修改不会影响原来的值，见例sum()
		2、如果想影响原来的值，可以通过指针的方式传参，见例sumPlus()
	*/
	//var sumArg1 float64 = 1.0
	//var sumArg2 float64 = 2.4
	//var sumResult float64
	//sumResult = sum(sumArg1, sumArg2)
	//fmt.Printf("sumArg1: %.2f, sumArg2: %.2f, sumResult: %.2f\n", sumArg1, sumArg2, sumResult)
	//sumPlus(&sumArg1, sumArg2)
	//fmt.Printf("sumArg1: %.2f, sumArg2: %.2f\n", sumArg1, sumArg2)

	// 函数可以作为形参
	//funcArg(sum, 1.0, 2.0)

	// 自定义数据类型，见mySum
	//funcArg2(sum, 2.0, 3.0)

	// 可以给返回值命名
	//name1, _ := returnWithName("asda", "zxcz")
	//fmt.Println(name1)

	// 支持可变参数，可变参数要写在最后
	//multiArgTest2(13, 2, 3, 4, 54, 5, 6, 6, 7)

	// 匿名函数，定义时调用，求两数的和
	res := func(n1 int, n2 int) int {
		return n1 + n2
	}(10, 20)
	fmt.Println(res)

	//  匿名函数，定义时赋值给变量，求两数的差
	funcA := func(n1 int, n2 int) int {
		return n1 - n2
	}
	fmt.Println(funcA(1, 2))

	// 全局匿名函数的使用
	fmt.Println(func1(4, 5))
}

func calculateTest() {
	var n1 float64 = 10
	var n2 float64 = 10
	var operator string = "+"
	var res float64
	res = utils.Calculate(n1, n2, operator)
	fmt.Printf("%.2f %s %.2f = %.2f\n", n1, operator, n2, res)
	operator = "*"
	res = utils.Calculate(n1, n2, operator)
	fmt.Printf("%.2f %s %.2f = %.2f\n", n1, operator, n2, res)

}

func recursiveTest(n int, i int) {
	if n > 10 {
		i++
		n--
		recursiveTest(n, i)
	} else {
		fmt.Println("n not larger than 10, n =", n, ",i =", i)
	}
}

func justReturnArgs(arg1 int, arg2 string) (int, string) {
	return arg1, arg2
}

func returnWithName(name1 string, name2 string) (n1 string, n2 string) {
	n1 = name1
	n2 = name2
	return
}

func sum(n1 float64, n2 float64) float64 {
	return n1 + n2
}

func sumPlus(n1 *float64, n2 float64) {
	*n1 = *n1 + n2
}

func funcArg(sumFunc func(float64, float64) float64, n1 float64, n2 float64) {
	fmt.Println("funcArg")
	fmt.Printf("sumArg1: %.2f, sumArg2: %.2f, sumResult: %.2f\n", n1, n2, sumFunc(n1, n2))
}

func funcArg2(sumFunc mySum, n1 float64, n2 float64) {
	fmt.Println("funcArg2")
	fmt.Printf("sumArg1: %.2f, sumArg2: %.2f, sumResult: %.2f\n", n1, n2, sumFunc(n1, n2))
}

func multiArgTest(args ...int) {
	sum := 0
	for i := 0; i < len(args); i++ {
		fmt.Printf("args[%d] = %d\n", i, args[i])
		sum += args[i]
	}
	fmt.Println("sum =", sum)
}

func multiArgTest2(sum int, abc ...int) {
	fmt.Println("sum =", sum)
	for i := 0; i < len(abc); i++ {
		fmt.Printf("args[%d] = %d\n", i, abc[i])
		sum += abc[i]
	}
	fmt.Println("sum =", sum)
}
